package com.whut.controller;

import com.whut.domain.*;
import com.whut.handler.*;
import com.whut.handler.extend.AsyncCreateMultiVMHandler;
import com.whut.handler.extend.AsyncDelMultiVMHandler;
import com.whut.handler.extend.AsyncGetMultiVMStatusHandler;
import com.whut.handler.extend.AsyncGetMultiVMUrlHandler;
import com.whut.service.AsyncOpenStackService;
import com.whut.service.OpenStackService;
import com.whut.service.QuotaService;
import com.whut.service.VHostService;
import com.whut.util.JsonUtil;
import com.whut.wesocket.PollWebSocketServlet;
import net.minidev.json.JSONUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import static com.whut.util.DateUtil.getNowTimeMS;
import static com.whut.util.SystemUtil.getMd5;

/**
 * Created by YY on 2018-01-14.
 */
@Controller
@RequestMapping("/instance")
public class InstanceController {

    private static final Map<String,String> md5Map=new TreeMap<>();
    private final PollWebSocketServlet webSocketServlet;
    private final AsyncCreateMultiVMHandler asyncCreateMultiVMHandler;
    private final AsyncDelMultiVMHandler asyncDelMultiVMHandler;
    private final AsyncGetMultiVMUrlHandler asyncGetMultiVMUrlHandler;
    private final AsyncGetMultiVMStatusHandler asyncGetMultiVMStatusHandler;
    private final CreateSigleVMHandler createSigleVMHandler;
    private final OpenStackService openStackService;
    private final VHostService vHostService;
    private final QuotaService quotaService;
    @Autowired
    public InstanceController(AsyncCreateMultiVMHandler asyncCreateMultiVMHandler, AsyncGetMultiVMUrlHandler asyncGetMultiVMUrlHandler, AsyncGetMultiVMStatusHandler asyncGetMultiVMStatusHandler, CreateSigleVMHandler createSigleVMHandler, PollWebSocketServlet webSocketServlet, AsyncDelMultiVMHandler asyncDelMultiVMHandler, OpenStackService openStackService, VHostService vHostService, QuotaService quotaService) {
        this.asyncCreateMultiVMHandler = asyncCreateMultiVMHandler;
        this.asyncGetMultiVMUrlHandler = asyncGetMultiVMUrlHandler;
        this.asyncGetMultiVMStatusHandler = asyncGetMultiVMStatusHandler;
        this.createSigleVMHandler = createSigleVMHandler;
        this.webSocketServlet = webSocketServlet;
        this.asyncDelMultiVMHandler = asyncDelMultiVMHandler;
        this.openStackService = openStackService;
        this.vHostService = vHostService;
        this.quotaService = quotaService;
    }
    /**
     * 获取MD5的前8位
     *
     * @param request HttpServletRequest
     * @return md5
     * @throws NoSuchAlgorithmException 异常
     */
    @RequestMapping("/getSimpleMd5")
    @ResponseBody
    public String getSimpleMd5(HttpServletRequest request) throws NoSuchAlgorithmException {
        User user = (User)request.getSession().getAttribute("user");
        String md5str="";
        if(user!=null) {
            String username = user.getUserName();
            md5str = getMd5(getNowTimeMS() + request.getSession().toString()).substring(0,8);
            md5Map.put(username+"/instance",md5str);
        }
        return md5str;
    }
    //通过查询本地数据库同步表格,返回map中含有实例的ID，作为前台表中每一行的ID号，对实例的操作全部用ID来一一对应
    @PostMapping("/getInstancesOfUserInDataBase")
    @ResponseBody //表示返回的是数据
    public List<Map<String,String>> getInstancesOfUserInDataBase(HttpServletRequest request){
        List<Map<String,String>> list = new ArrayList<>();
        User user = (User)request.getSession().getAttribute("user");
        if(user!=null) {
            String username = user.getUserName();
            list = vHostService.selectVhostsByUserNameToListMap(username);
        }
        return list;
    }
    //通过查询本地数据库同步表格,返回map中含有实例的ID，作为前台表中每一行的ID号，对实例的操作全部用ID来一一对应
    @PostMapping("/getQuotaOfUserInDataBase")
    @ResponseBody //表示返回的是数据
    public Map<String,String> getQuotaOfUserInDataBase(HttpServletRequest request){
        Map<String,String> map = new TreeMap<>();
        User user = (User)request.getSession().getAttribute("user");
        if(user!=null) {
            String username = user.getUserName();
            OpenStackUserQuota quota = quotaService.selectQuotaByUserName(username);
            map.put("maxInstance", quota.getMaxinstance());
            map.put("maxCpu",quota.getMaxcpu());
            map.put("maxRam",quota.getMaxram());
            map.put("maxDisk",quota.getMaxdisk());
            map.put("currentInstance",quota.getCurrentinstance());
            map.put("currentCpu",quota.getCurrentcpu());
            map.put("currentRam",quota.getCurrentram());
            map.put("currentDisk",quota.getCurrentdisk());
        }
        return map;
    }
    @PostMapping("/changeUserQuota")
    @ResponseBody //表示返回的是数据
    public int changeUserQuota(HttpServletRequest request){
        User user = (User)request.getSession().getAttribute("user");
        if(user!=null) {
            String username = user.getUserName();
            OpenStackUserQuota quota = quotaService.selectQuotaByUserName(username);
            String instance = request.getParameter("instance");
            String vcpu = request.getParameter("vcpu");
            String ram = request.getParameter("ram");
            String disk = request.getParameter("disk");
            String isAdd = request.getParameter("isAdd");
            if(openStackService.updateOpenStackUserMaxQuota(username,Boolean.valueOf(isAdd),instance,vcpu,ram,disk)){
                return 200;
            }else {
                return 400;
            }
        }
        return 404;
    }



    /*
   * 创建实例，提交表单
   * */
    //not ok
    @PostMapping("/createSingle")
    @ResponseBody //表示返回的是数据
    public int createSingle(HttpServletRequest request){
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            String username = user.getUserName();
            String password = user.getPassWord();
            String instance = request.getParameter("instance");
            String image = request.getParameter("image");
            String vcpu = request.getParameter("vcpu");
            String ram = request.getParameter("ram");
            String disk = request.getParameter("disk");
            createSigleVMHandler.setParameterOfHandler(new CreateParameter(username,password,instance,image,vcpu,ram,disk));
            createSigleVMHandler.setWebSocketServlet(md5Map.get(username+"/instance"),webSocketServlet);
            Thread thread=new Thread(createSigleVMHandler);
            thread.start();
            return 200;
        }
        return 404;
    }
    //ok
    @PostMapping("/syncSingleUrl")
    @ResponseBody //表示返回的是数据
    public Map<String,String> syncSingleUrl(HttpServletRequest request){
        User user = (User)request.getSession().getAttribute("user");
        if(user!=null) {
            String username = user.getUserName();
            String password = user.getPassWord();
            String instance_id = request.getParameter("instance_id");
            return openStackService.getUrlAndUpdateDatabase(username,password,instance_id);
        }
        return null;
    }
    //ok
    @PostMapping("/syncSingleStatus")
    @ResponseBody //表示返回的是数据
    public Map<String,String> syncSingleStatus(HttpServletRequest request){
        User user = (User)request.getSession().getAttribute("user");
        if(user!=null) {
            String username = user.getUserName();
            String password = user.getPassWord();
            String instance_id = request.getParameter("instance_id");
            return openStackService.getStatusAndUpdateDatabase(username,password,instance_id);
        }
        return null;
    }
    //not ok
    @PostMapping(value = "/operateSingle")
    @ResponseBody //表示返回的是数据
    public Map<String,String> operateInstance(HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            String username = user.getUserName();
            String password = user.getPassWord();
            String instance_id = request.getParameter("instance_id");
            String operate = request.getParameter("operate");
            switch (operate){
                    case "start":return openStackService.startVirtualMachine(username,password,instance_id);
                    case "stop":return openStackService.stopVirtualMachine(username,password,instance_id);
                    case "suspend":return openStackService.suspendVirtualMachine(username,password,instance_id);
                    case "resume":return openStackService.resumeVirtualMachine(username,password,instance_id);
                    case "pause":return openStackService.pauseVirtualMachine(username,password,instance_id);
                    case "unpause":return openStackService.unpauseVirtualMachine(username,password,instance_id);
                    case "reboot":return openStackService.rebootVirtualMachine(username,password,instance_id);
                    case "lock":return openStackService.lockVirtualMachine(username,password,instance_id);
                    case "unlock":return openStackService.unlockVirtualMachine(username,password,instance_id);
                    case "delete":return openStackService.deleteVirtualMachine(username,password,instance_id);
                    default:
                    return null;
            }
        }
        return null;
    }



    //以下是多台虚拟机一起操作，利用异步方法
    /*
* 创建实例，提交表单
* */
    @PostMapping("/createMulti")
    @ResponseBody //表示返回的是数据
    public int createMulti(HttpServletRequest request){
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            String username = user.getUserName();
            String password = user.getPassWord();
            String json = request.getParameter("instanceArray");
            try {
                JSONArray jsonArray =new JSONArray(json);
                CreateParameter[] createParameters = JsonUtil.JsonArray2CreateParameterArray(username,password,jsonArray);
                asyncCreateMultiVMHandler.setCreateParameters(createParameters);
                asyncCreateMultiVMHandler.setWebSocketServlet(md5Map.get(username+"/instance"),webSocketServlet);
                Thread thread=new Thread(asyncCreateMultiVMHandler);
                thread.start();
                return 200;
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return 404;
    }

    @PostMapping(value = "/deleteMulti")
    @ResponseBody //表示返回的是数据
    public int deleteMulti(HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            String username = user.getUserName();
            String password = user.getPassWord();
            String json = request.getParameter("instanceIdArray");
            try {
                JSONArray jsonArray =new JSONArray(json);
                Parameter[] parameters = JsonUtil.JsonArray2ParameterArray(username,password,jsonArray);
                asyncDelMultiVMHandler.setParameters(parameters);
                asyncDelMultiVMHandler.setWebSocketServlet(md5Map.get(username+"/instance"),webSocketServlet);
                Thread thread=new Thread(asyncDelMultiVMHandler);
                thread.start();
                return 200;
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return 404;
    }

    @PostMapping(value = "/syncMultiUrl")
    @ResponseBody //表示返回的是数据
    public int syncMultiUrl(HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            String username = user.getUserName();
            String password = user.getPassWord();
            String json = request.getParameter("instanceIdArray");
            //如果没有任何的同步参数，默认同步所有的实例
            if(json==null){
                List<Vhost> vhosts=vHostService.selectVhostsByUserName(username);
                Parameter[] array=new Parameter[vhosts.size()];
                for(int i=0;i!=vhosts.size();++i){
                    array[i]=new Parameter(username,password,vhosts.get(i).getHostid());
                }
                asyncGetMultiVMUrlHandler.setParameters(array);
                asyncGetMultiVMUrlHandler.setWebSocketServlet(md5Map.get(username+"/instance"),webSocketServlet);
                Thread thread=new Thread(asyncGetMultiVMUrlHandler);
                thread.start();
                return 200;
            }
            //否则只同步选择的实例
            try {
                asyncGetMultiVMUrlHandler.setParameters(JsonUtil.JsonArray2ParameterArray(username,password,new JSONArray(json)));
                asyncGetMultiVMUrlHandler.setWebSocketServlet(md5Map.get(username+"/instance"),webSocketServlet);
                Thread thread=new Thread(asyncGetMultiVMUrlHandler);
                thread.start();
                return 200;
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return 404;
    }
    @PostMapping(value = "/syncMultiStatus")
    @ResponseBody //表示返回的是数据
    public int syncMultiStatus(HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            String username = user.getUserName();
            String password = user.getPassWord();
            String json = request.getParameter("instanceArray");
            //如果没有任何的同步参数，默认同步所有的实例
            if(json==null){
                List<Vhost> vhosts=vHostService.selectVhostsByUserName(username);
                Parameter[] array=new Parameter[vhosts.size()];
                for(int i=0;i!=vhosts.size();++i){
                    array[i]=new Parameter(username,password,vhosts.get(i).getHostid());
                }
                asyncGetMultiVMStatusHandler.setParameters(array);
                asyncGetMultiVMStatusHandler.setWebSocketServlet(md5Map.get(username+"/instance"),webSocketServlet);
                Thread thread=new Thread(asyncGetMultiVMStatusHandler);
                thread.start();
                return 200;
            }
            //否则只同步选择的实例
            try {
                asyncGetMultiVMStatusHandler.setParameters(JsonUtil.JsonArray2ParameterArray(username,password,new JSONArray(json)));
                asyncGetMultiVMStatusHandler.setWebSocketServlet(md5Map.get(username+"/instance"),webSocketServlet);
                Thread thread=new Thread(asyncGetMultiVMStatusHandler);
                thread.start();
                return 200;
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return 404;
    }
    //以下接口不常用
    @PostMapping(value = "/getInstanceOptions")
    @ResponseBody //表示返回的是数据
    public List<String> getInstanceOptions(HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            String instance_id = request.getParameter("instance_id");
            return openStackService.getVirtualMachineCurrentAvailableOptions(instance_id);
        }
        return null;
    }
    @PostMapping(value = "/getInstanceOptionsCode")
    @ResponseBody //表示返回的是数据
    public List<Integer> getInstanceOptionsCode(HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            String instance_id = request.getParameter("instance_id");
            return openStackService.getVirtualMachineCurrentAvailableOptionsCode(instance_id);
        }
        return null;
    }
    @PostMapping(value = "/getPasswordAndIp")
    @ResponseBody //表示返回的是数据
    public Map<String,String> getPasswordAndIp(HttpServletRequest request) {
        Map<String,String> map =new TreeMap<>();
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            String instance_id = request.getParameter("instance_id");
            Vhost vhost =vHostService.selectVhostByHostId(instance_id);
            if(vhost!=null){
                String address = vhost.getIp().replaceAll("provider=","");
                String password = user.getPassWord();
                map.put("address",address);
                map.put("password",password);
                return map;
            }
        }
        return null;
    }
}
